package com.offcn.user.controller;

import com.alibaba.fastjson.JSON;
import com.offcn.common.utils.JwtUtil;
import com.offcn.common.utils.TokenDecode;
import com.offcn.user.pojo.User;
import com.offcn.user.service.UserService;
import com.offcn.common.entity.PageResult;
import com.offcn.common.entity.Result;
import com.offcn.common.entity.StatusCode;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.bcrypt.BCrypt;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

/**
 * @Author:ujiuye
 * @Description:
 * @Date 2021/2/1 14:19
 *****/
@Api(tags = "UserController")
@RestController
@RequestMapping("/user")
@CrossOrigin
public class UserController {

    @Autowired
    private UserService userService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;


    @Autowired
    private TokenDecode tokenDecode;

    /**
     * User分页条件搜索实现
     * @param user
     * @param page
     * @param size
     * @return
     */
    @ApiOperation(value = "User条件分页查询", notes = "分页条件查询User方法详情", tags = {"UserController"})
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "path", name = "page", value = "当前页", required = true),
            @ApiImplicitParam(paramType = "path", name = "size", value = "每页显示条数", required = true)
    })
    @PostMapping(value = "/search/{page}/{size}")
    public Result<PageResult<User>> findPage(@RequestBody(required = false) @ApiParam(name = "User对象", value = "传入JSON数据", required = false) User user, @PathVariable int page, @PathVariable int size) {
        //调用UserService实现分页条件查询User
        PageResult<User> pageResult = userService.findPage(user, page, size);
        return new Result(true, StatusCode.OK, "查询成功", pageResult);
    }

    /**
     * User分页搜索实现
     * @param page:当前页
     * @param size:每页显示多少条
     * @return
     */
    @ApiOperation(value = "User分页查询", notes = "分页查询User方法详情", tags = {"UserController"})
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "path", name = "page", value = "当前页", required = true),
            @ApiImplicitParam(paramType = "path", name = "size", value = "每页显示条数", required = true)
    })
    @GetMapping(value = "/search/{page}/{size}")
    public Result<PageResult<User>> findPage(@PathVariable int page, @PathVariable int size) {
        //调用UserService实现分页查询User
        PageResult<User> pageResult = userService.findPage(page, size);
        return new Result<PageResult<User>>(true, StatusCode.OK, "查询成功", pageResult);
    }

    /**
     * 多条件搜索品牌数据
     * @param user
     * @return
     */
    @ApiOperation(value = "User条件查询", notes = "条件查询User方法详情", tags = {"UserController"})
    @PostMapping(value = "/search")
    public Result<List<User>> findList(@RequestBody(required = false) @ApiParam(name = "User对象", value = "传入JSON数据", required = false) User user) {
        //调用UserService实现条件查询User
        List<User> list = userService.findList(user);
        return new Result<List<User>>(true, StatusCode.OK, "查询成功", list);
    }

    /**
     * 根据ID删除品牌数据
     * @param id
     * @return
     */
    @ApiOperation(value = "User根据ID删除", notes = "根据ID删除User方法详情", tags = {"UserController"})
    @ApiImplicitParam(paramType = "path", name = "id", value = "主键ID", required = true, dataType = "Long")
    @PreAuthorize("hasAnyAuthority('admin')")  //表示只有admin角色才能访问该方法，其他角色无权访问
    @DeleteMapping(value = "/{id}")
    public Result delete(@PathVariable Long id) {
        //调用UserService实现根据主键删除
        userService.delete(id);
        return new Result(true, StatusCode.OK, "删除成功");
    }

    /**
     * 修改User数据
     * @param user
     * @param id
     * @return
     */
    @ApiOperation(value = "User根据ID修改", notes = "根据ID修改User方法详情", tags = {"UserController"})
    @ApiImplicitParam(paramType = "path", name = "id", value = "主键ID", required = true, dataType = "Long")
    @PutMapping(value = "/{id}")
    public Result update(@RequestBody @ApiParam(name = "User对象", value = "传入JSON数据", required = false) User user, @PathVariable Long id) {
        //设置主键值
        user.setId(id);
        //调用UserService实现修改User
        userService.update(user);
        return new Result(true, StatusCode.OK, "修改成功");
    }

    /**
     * 新增User数据
     * @param user
     * @return
     */
    @ApiOperation(value = "User添加", notes = "添加User方法详情", tags = {"UserController"})
    @PostMapping("/add")
    public Result add(@RequestBody @ApiParam(name = "User对象", value = "传入JSON数据", required = true) User user, String code) {
        //用户名、密码验证
        if (StringUtils.isEmpty(user.getPassword())) {
            return new Result(false, StatusCode.ERROR, "密码不能为空");
        }
        if (StringUtils.isEmpty(user.getUsername())) {
            return new Result(false, StatusCode.ERROR, "用户名不能为空 ");
        }

        //验证码验证
        String redisCode = stringRedisTemplate.boundValueOps(user.getPhone()).get();
        if (redisCode == null) {
            return new Result(false, StatusCode.ERROR, "验证码超时，请重新获取");
        }

        if (!code.equals(redisCode)) {
            return new Result(false, StatusCode.ERROR, "验证码有误");
        }

        user.setCreated(new Date());
        user.setUpdated(new Date());
        user.setStatus("Y");
        //获取密码
        String password = user.getPassword();
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        //生成加密后的新密码
        password = bCryptPasswordEncoder.encode(password);
        user.setPassword(password);

        //调用UserService实现添加User
        userService.add(user);
        return new Result(true, StatusCode.OK, "添加成功");
    }

    /**
     * 根据ID查询User数据
     * @param id
     * @return
     */
    @ApiOperation(value = "User根据ID查询", notes = "根据ID查询User方法详情", tags = {"UserController"})
    @ApiImplicitParam(paramType = "path", name = "id", value = "主键ID", required = true, dataType = "Long")
    @GetMapping("/{id}")
    public Result<User> findById(@PathVariable Long id) {
        //调用UserService实现根据主键查询User
        User user = userService.findById(id);
        return new Result<User>(true, StatusCode.OK, "查询成功", user);
    }

    /**
     * 查询User全部数据
     * @return
     */
    @ApiOperation(value = "查询所有User", notes = "查询所User有方法详情", tags = {"UserController"})
    @GetMapping
    public Result<List<User>> findAll(HttpServletRequest request) {
        //获取令牌信息
        String header = request.getHeader("Authorization");
        System.out.println("令牌信息："+header);
        //调用UserService实现查询所有User
        List<User> list = userService.findAll();
        return new Result<List<User>>(true, StatusCode.OK, "查询成功", list);
    }

    /**
     * 生成验证码
     *
     * @return
     */
    @ApiOperation(value = "生成验证码", notes = "生成验证码详情", tags = {"UserController"})
    @GetMapping("createCode")
    public Result createCode(@RequestParam(required = false) String phone) {
        try {
            userService.createCode(phone);
            return new Result<List<User>>(true, StatusCode.OK, "生成成功");
        } catch (Exception e) {
            e.printStackTrace();
            return new Result<List<User>>(false, StatusCode.ERROR, "生成失败");
        }
    }

    /**
     * 用户登录
     *
     * @param username 用户名
     * @param password 用密码
     * @return 返回是否登录成功
     */
    @RequestMapping("login")
    public Result login(String username, String password, HttpServletResponse response) {
        //查询用户信息
        User user = userService.findByUserName(username);
        //判断用户名是否存在,并且判断传过来的密码是否和加密后的密码一样
        if (user != null && BCrypt.checkpw(password, user.getPassword())) {
            //设置令牌信息
            HashMap<String, Object> info = new HashMap<>();
            info.put("role", "USER");
            info.put("succes", "SUCCES");
            info.put("username", username);
            //生成令牌
            String jwt = JwtUtil.createJWT(UUID.randomUUID().toString(), JSON.toJSONString(info), null);

            //将令牌放入cookie
            Cookie cookie = new Cookie("Authorization", jwt);
            response.addCookie(cookie);

            return new Result(true, StatusCode.OK, "登录成功", jwt);

        }
        return new Result(false, StatusCode.ERROR, "账号或密码有误，请重新输入！");
    }

    /**
     * 通过用户名查询信息
     * @param username
     * @return
     */
    @GetMapping("load/{username}")
    public Result<User> finghByUserName(@PathVariable(value = "username") String username){
        //调用UserService实现主键查询User
        User user = userService.findByUserName(username);
        return new Result<User>(true, StatusCode.OK, "查询成功",user);
    }

    /**
     * 增加用户积分
     * @param points:要添加的积分
     */
    @GetMapping(value = "/points/add")
    public Result addPoints(@RequestParam("points") Integer  points){
        //获取用户名
        Map<String, String> userInfo = tokenDecode.getUserInfo();
        String username = userInfo.get("username");
        if (StringUtils.isEmpty(username)||username.equals("")) {
            username = "ujiuye";
        }

        //添加积分
        userService.addUserPoints(username,points);
        return new Result<User>(true, StatusCode.OK, "添加积分成功");
    }
}
